home *** CD-ROM | disk | FTP | other *** search
/ MacHack 1997 / MacHack 1997.toast / Hacks / Hacks ’93 / OK, What was that again? / Extension / OK.c < prev    next >
C/C++ Source or Header  |  1993-06-17  |  13KB  |  504 lines

  1. #include <Dialogs.h>
  2. #include <GestaltEqu.h>
  3. #ifndef        __TYPES__
  4. #include    <Types.h>
  5. #endif
  6.  
  7. #ifndef        __MEMORY__
  8. #include    <Memory.h>
  9. #endif
  10.  
  11. #ifndef        __ERRORS__
  12. #include    <Errors.h>
  13. #endif
  14.  
  15. #ifndef        __TRAPS__
  16. #include    <Traps.h>
  17. #endif
  18.  
  19. #ifndef        __OSUTILS__
  20. #include    <OSUtils.h>
  21. #endif
  22.  
  23. #ifndef        __TOOLUTILS__
  24. #include    <ToolUtils.h>
  25. #endif
  26.  
  27. #ifndef        __NOTIFICATION_
  28. #include    <Notification.h>
  29. #endif
  30. #include <Resources.h>
  31. #include <StdDef.h>
  32. #include <SysEqu.h>
  33. #include "OSUtilsSup.h"
  34. #include "Icons.h"
  35.     
  36. pascal void ShowINIT(short iconID, short moveX);
  37. pascal void MessageModalDialog(ModalFilterProcPtr filterProc,short *itemHit);
  38. pascal OSErr MessageGestalt(OSType selector, long *response);
  39. pascal Boolean MessageFilterProc(DialogPtr theDialog, EventRecord* theEvent, short* itemHit);
  40. void foo(void);
  41. void Globals(void);
  42. void PostNotification(void);
  43. pascal OSErr DetachIcon(ResType, Handle* theIcon, void*);
  44.  
  45. typedef pascal void (*TModalDialog)(ModalFilterProcPtr, short*);
  46.  
  47. typedef struct SLocals {
  48.     struct SLocals*        oldLocals;
  49.     long                ticks;
  50.     ModalFilterProcPtr    filterProc;
  51.     short                stage;
  52.     Boolean                timedOut;
  53.     Rect                mouseSlop;
  54. //    GrafPort            bwPort;
  55. //    GrafPort            colorPort;
  56.     WindowPtr            window;
  57.     Boolean                isBWPort;
  58. };
  59. typedef struct SLocals SLocals;
  60.  
  61. struct SGlobals {
  62.     TModalDialog    modalDialogProc;
  63.     SLocals*        locals;
  64.     
  65.     Handle            iconSuites[6];
  66.     NMRec            notifyRec;
  67. };
  68. typedef struct SGlobals SGlobals;
  69.  
  70. struct SMessage {
  71.     QHdr        header;
  72.     NMRecPtr    notify;
  73. };
  74. typedef struct SMessage SMessage;
  75.  
  76. void main(void)
  77. {
  78.     SGlobals*    globals        = (SGlobals*)Globals;
  79.     Handle*        iconSuite    = &globals->iconSuites;
  80.     short        i;
  81.     OSErr        error;
  82.     THz            zone;
  83.     Handle         iconHandle;
  84.     
  85.     SMessage* q = (SMessage*)foo;
  86.     
  87.     q->header.qFlags = 0;
  88.     q->header.qHead = nil;
  89.     q->header.qTail = nil;
  90.     q->notify = nil;
  91.     
  92.     NewGestalt('Msg!',(ProcPtr)MessageGestalt);
  93.     
  94.     (void)PatchTrap((ProcPtr*)&globals->modalDialogProc, _ModalDialog, (ProcPtr)MessageModalDialog, 0);
  95.     DetachResource(RecoverHandle((Ptr)main));
  96.     
  97.     zone = GetZone();
  98.     SetZone(SystemZone());
  99.     for (i = 512; i <= 517; ++i) {
  100.         error = GetIconSuite(iconSuite, i, svAllLargeData);
  101.         error = ForEachIconDo(*iconSuite, svAllLargeData, (ProcPtr)DetachIcon, nil);
  102.         ++iconSuite;
  103.     }
  104.  
  105.     iconHandle = GetResource('SICN', 128);
  106.     DetachResource(iconHandle);
  107.     HNoPurge(iconHandle);
  108.  
  109.     globals->notifyRec.qType = nmType;
  110.     globals->notifyRec.nmMark = 0;                 // item to mark in Apple menu
  111.     globals->notifyRec.nmIcon = iconHandle;        // handle to small icon
  112.     globals->notifyRec.nmSound = nil;            // no sound
  113.     globals->notifyRec.nmStr = nil;                // no alert
  114.     globals->notifyRec.nmResp = nil;            // no response routine
  115.         
  116.     SetZone(zone);
  117.     
  118.     ShowINIT(128,-1);
  119.  
  120. }
  121.  
  122. pascal OSErr DetachIcon(ResType, Handle* theIcon, void*)
  123. {
  124.     if (*theIcon) DetachResource(*theIcon);
  125.     return noErr;
  126. }
  127.  
  128. void PostNotification(void)
  129. {
  130.     SGlobals*    globals = (SGlobals*)Globals;
  131.     SMessage* q = (SMessage*)foo;
  132.  
  133.     // only post a notification if this is the first dialog dismissed since last viewed
  134.  
  135.     if (q->header.qHead == nil) {
  136.         q->notify = &globals->notifyRec;
  137.         NMInstall(&globals->notifyRec);
  138.     }
  139. }
  140.  
  141. void Globals(void)
  142. {
  143.     Debugger();
  144.     Debugger();
  145.     Debugger();
  146.     Debugger();
  147.     Debugger();
  148.     Debugger();
  149.     Debugger();
  150.     Debugger();
  151.     Debugger();
  152.     Debugger();
  153.     Debugger();
  154.     Debugger();
  155.     Debugger();
  156.     Debugger();
  157.     Debugger();
  158.     Debugger();
  159.     Debugger();
  160.     Debugger();
  161.     Debugger();
  162.     Debugger();
  163.     Debugger();
  164.     Debugger();
  165.     Debugger();
  166.     Debugger();
  167.     Debugger();
  168.     Debugger();
  169.     Debugger();
  170.     Debugger();
  171.     Debugger();
  172.     Debugger();
  173.     Debugger();
  174.     Debugger();
  175.     Debugger();
  176.     Debugger();
  177.     Debugger();
  178.     Debugger();
  179.     Debugger();
  180. }
  181.  
  182. void foo(void)
  183. {
  184.     Debugger();
  185.     Debugger();
  186.     Debugger();
  187.     Debugger();
  188.     Debugger();
  189.     Debugger();
  190.     Debugger();
  191.     Debugger();
  192. }
  193.  
  194. pascal OSErr MessageGestalt(OSType, long *response)
  195. {
  196.     *response = (long)foo;
  197.     return noErr;
  198. }
  199.  
  200. typedef struct {
  201.     struct QElem *qLink;            /* QElement header */
  202.     short qType;
  203.     
  204.     PicHandle        picture;
  205.     unsigned long    dateTime;
  206.     Rect            windowRect;
  207.     Str31            appName;
  208. } Q;
  209.  
  210. enum {
  211.     fingerFromLeft    = 7,
  212.     fingerFromTop    = 10,
  213.     fingerSize        = 32,
  214.  
  215.     lastStage        = 5,                        /* Dismiss Dialog when this stage is met */
  216.     secondsPerStage    = 1,                        /* Time for each stage */
  217.     startTime        = 60 * 5,                    /* Start to fade after n seconds */
  218.     delayTime        = 60 * secondsPerStage,        /* Delta between stages in n seconds */
  219.     slopAmount        = 4                            /* Reset when mouse moves by this */
  220. };
  221.  
  222. pascal void MessageModalDialog(ModalFilterProcPtr filterProc,short *itemHit)
  223. {
  224.     SGlobals*    globals = (SGlobals*)Globals;
  225.     PicHandle     picture;
  226.     GrafPtr        theDialog;
  227.     THz            zone;
  228.     Q*            q;
  229.     GrafPtr        oldPort;
  230.     SMessage*    message;
  231.     short        itemType;
  232.     Handle        handle;
  233.     Rect        box, iconBox;
  234.     Str255        title;
  235.     SLocals        locals;
  236.     Point        mouse;
  237.     
  238.     GetMouse(&mouse);
  239.     theDialog = FrontWindow();
  240.     
  241.     GetDItem(theDialog, ok, &itemType, &handle, &box);
  242.     
  243.     if (itemType != 4) goto bannana;
  244.     GetCTitle((ControlHandle)handle, title);
  245.     if (title[0] != 2) goto bannana;
  246.     if (title[1] != 'O') goto bannana;
  247.     if (title[2] != 'K') goto bannana;
  248.         
  249.     if ((theDialog->portBits.rowBytes & 0xC000) != 0xC000) {
  250.         locals.isBWPort = true;
  251.         
  252.         // BlockMove(theDialog, &locals.bwPort, sizeof(GrafPort)); /* Make a copy of the Port */
  253.         
  254.         GetPort(&oldPort);
  255.         
  256.         iconBox = theDialog->portRect;
  257.         OffsetRect(&iconBox, - theDialog->portBits.bounds.left, - theDialog->portBits.bounds.top);
  258.         locals.window = NewCWindow(nil, &iconBox, "\p", false, 0, (WindowPtr)-1, false, nil);
  259.         #if false
  260.         
  261.         OpenCPort((CGrafPtr)&locals.colorPort);                    /* Init a color Port */
  262.         
  263.         /* Set up the color port to match the bw port */
  264.         PortSize(theDialog->portRect.right - theDialog->portRect.left,
  265.             theDialog->portRect.bottom - theDialog->portRect.top);
  266.         MovePortTo(- theDialog->portBits.bounds.left, - theDialog->portBits.bounds.top);
  267.         CopyRgn(theDialog->visRgn, locals.colorPort.visRgn);
  268.         CopyRgn(theDialog->clipRgn, locals.colorPort.clipRgn);
  269.         BlockMove(&theDialog->pnLoc, &locals.colorPort.pnLoc, offsetof(GrafPort, pnPat) - offsetof(GrafPort, pnLoc));
  270.         BlockMove(&theDialog->pnVis, &locals.colorPort.pnVis, sizeof(GrafPort) - offsetof(GrafPort, pnVis));
  271.         
  272.         #endif
  273.         
  274.         SetPort(oldPort);
  275.     } else {
  276.         locals.isBWPort = false;
  277.     }
  278.         
  279.     locals.filterProc    = filterProc;
  280.     locals.ticks        = TickCount();
  281.     locals.timedOut        = false;
  282.     locals.stage        = 0;
  283.     locals.oldLocals    = globals->locals;
  284.     SetRect(&locals.mouseSlop, mouse.h, mouse.v,
  285.         mouse.h, mouse.v);
  286.     InsetRect(&locals.mouseSlop, -slopAmount, -slopAmount);
  287.     
  288.     globals->locals = &locals;
  289.  
  290. #define CallTheOldTrap    (globals->modalDialogProc)
  291.     
  292.     CallTheOldTrap(MessageFilterProc, itemHit);
  293.     
  294.     globals->locals = locals.oldLocals;
  295.     
  296.     if (locals.timedOut) {
  297.             
  298.         GetPort(&oldPort);
  299.         SetPort(theDialog);
  300.         
  301.         zone = GetZone();
  302.         SetZone(SystemZone());
  303.         picture = OpenPicture(&theDialog->portRect);
  304.         SetZone(zone);
  305.         
  306.         InvalRect(&theDialog->portRect);
  307.         ClipRect(&theDialog->portRect);
  308.     
  309.         /*    If there is a filter proc then send it an update event to force any
  310.             additional drawing. */
  311.         if (filterProc) {
  312.             EventRecord theEvent = { updateEvt, (long)theDialog, TickCount(), { 0, 0 }, 0 };
  313.         
  314.             (void)filterProc(theDialog, &theEvent, itemHit);
  315.         }
  316.         
  317.         if (!EmptyRgn(((WindowPeek)theDialog)->updateRgn)) {
  318.             BeginUpdate(theDialog);
  319.             DrawDialog(theDialog);
  320.             EndUpdate(theDialog);
  321.         }
  322.         
  323.         iconBox.left = ((box.left + box.right) >> 1) - fingerFromLeft;
  324.         iconBox.right = iconBox.left + fingerSize;
  325.         iconBox.top = ((box.top + box.bottom) >> 1) - fingerFromTop;
  326.         iconBox.bottom = iconBox.top + fingerSize;
  327.         ClipRect(&theDialog->portRect);
  328.         PlotIconSuite(&iconBox, atNone, ttNone, globals->iconSuites[lastStage]);
  329.         
  330.         ClosePicture();
  331.         
  332.         
  333.         HiliteControl((ControlHandle)handle, 0);
  334.     
  335.         q = (Q*)NewPtrSys(sizeof(Q));
  336.         q->picture = picture;
  337.         GetDateTime(&q->dateTime);
  338.         q->windowRect = theDialog->portRect;
  339.         BlockMove((void*)CurApName, &q->appName, 32);
  340.         LocalToGlobal((Point*)&q->windowRect.top);
  341.         LocalToGlobal((Point*)&q->windowRect.bottom);
  342.         
  343.         PostNotification();
  344.         if (Gestalt('Msg!', (long*)&message) == noErr) Enqueue((QElemPtr)q, &message->header);
  345.         else {
  346.             DisposePtr((Ptr)q);
  347.             KillPicture(picture);
  348.         }
  349.         
  350.         SetPort(oldPort);
  351.         
  352.         *itemHit = ok;
  353.     }
  354.     if (locals.isBWPort) {
  355.         DisposeWindow(locals.window);
  356.         //CloseCPort((CGrafPtr)&locals.colorPort);
  357.     }
  358.     return;
  359. bannana:
  360.     CallTheOldTrap(filterProc, itemHit);
  361. }
  362.  
  363. pascal Boolean MessageFilterProc(DialogPtr theDialog, EventRecord* theEvent, short* itemHit)
  364. {
  365.     SGlobals*    globals    = (SGlobals*)Globals;
  366.     SLocals*    locals    = globals->locals;
  367.     short        itemType;
  368.     Handle        handle;
  369.     Rect        box, iconBox;
  370.     GrafPtr        currentPort;
  371.         
  372.     if (((theEvent->what >= mouseDown) && (theEvent->what <= autoKey))
  373.             || !PtInRect(theEvent->where, &locals->mouseSlop)) {
  374.         
  375.         /* Brighten the control */
  376.         
  377.         if (locals->stage != 0) {
  378.             RgnHandle    firstMask = NewRgn();
  379.             RgnHandle    secondMask = NewRgn();
  380.             
  381.             GetDItem(theDialog, ok, &itemType, &handle, &box);
  382.             GetPort(¤tPort);
  383.             SetPort(theDialog);
  384.             iconBox.left = ((box.left + box.right) >> 1) - fingerFromLeft;
  385.             iconBox.right = iconBox.left + fingerSize;
  386.             iconBox.top = ((box.top + box.bottom) >> 1) - fingerFromTop;
  387.             iconBox.bottom = iconBox.top + fingerSize;
  388.             (void)IconSuiteToRgn(firstMask, &iconBox, atNone, globals->iconSuites[locals->stage - 1]);
  389.  
  390.             if (locals->stage > lastStage) {
  391.                 RectRgn(secondMask, &box);
  392.                 UnionRgn(firstMask, secondMask, firstMask);
  393.                 (*(ControlHandle)handle)->contrlHilite = 0;
  394.             }
  395.             InvalRgn(firstMask);
  396.             
  397.             /*    If there is a filter proc then send it an update event to force any
  398.                 additional drawing. */
  399.             ClipRect(&theDialog->portRect);
  400.             EraseRgn(firstMask);
  401.             if (locals->filterProc) {
  402.                 EventRecord theEvent = { updateEvt, (long)theDialog, TickCount(), { 0, 0 }, 0 };
  403.             
  404.                 (void)locals->filterProc(theDialog, &theEvent, itemHit);
  405.             }
  406.             
  407.             if (!EmptyRgn(((WindowPeek)theDialog)->updateRgn)) {
  408.                 BeginUpdate(theDialog);
  409.                 DrawDialog(theDialog);
  410.                 EndUpdate(theDialog);
  411.             }            
  412.             
  413.             DisposeRgn(firstMask);
  414.             DisposeRgn(secondMask);
  415.             SetPort(currentPort);
  416.             locals->stage = 0;
  417.         }
  418.     
  419.         /* Reset the timer */
  420.         
  421.         locals->ticks = TickCount();
  422.         
  423.         /* Reset the mouseSlop */
  424.         
  425.         SetRect(&locals->mouseSlop, theEvent->where.h, theEvent->where.v,
  426.             theEvent->where.h, theEvent->where.v);
  427.         InsetRect(&locals->mouseSlop, -slopAmount, -slopAmount);
  428.         
  429.     } else if (locals->ticks + startTime + (locals->stage) * delayTime < TickCount()) {
  430.         if (locals->stage == 0) ObscureCursor();
  431.         if (locals->stage > lastStage) {
  432.             *itemHit = ok;
  433.             locals->timedOut = true;
  434.             return true;
  435.         } else {
  436.             RgnHandle    firstMask = NewRgn();
  437.             RgnHandle    secondMask = NewRgn();
  438.             
  439.             GetDItem(theDialog, ok, &itemType, &handle, &box);
  440.             GetPort(¤tPort);
  441.         
  442.             SetPort(theDialog);
  443.             iconBox.left = ((box.left + box.right) >> 1) - fingerFromLeft;
  444.             iconBox.right = iconBox.left + fingerSize;
  445.             iconBox.top = ((box.top + box.bottom) >> 1) - fingerFromTop;
  446.             iconBox.bottom = iconBox.top + fingerSize;
  447.             if (locals->stage != 0) {
  448.                 
  449.                 (void)IconSuiteToRgn(firstMask, &iconBox, atNone, globals->iconSuites[locals->stage - 1]);
  450.                 if (locals->stage == lastStage) {
  451.                     RectRgn(secondMask, &box);
  452.                     UnionRgn(firstMask, secondMask, firstMask);
  453.                     (*(ControlHandle)handle)->contrlHilite = inButton;
  454.                 }
  455.                 (void)IconSuiteToRgn(secondMask, &iconBox, atNone, globals->iconSuites[locals->stage]);
  456.                 DiffRgn(firstMask, secondMask, secondMask);
  457.                 InvalRgn(secondMask);
  458.                 /*    If there is a filter proc then send it an update event to force any
  459.                     additional drawing. */
  460.                 ClipRect(&theDialog->portRect);
  461.                 EraseRgn(secondMask);
  462.                 if (locals->filterProc) {
  463.                     EventRecord theEvent = { updateEvt, (long)theDialog, TickCount(), { 0, 0 }, 0 };
  464.                 
  465.                     (void)locals->filterProc(theDialog, &theEvent, itemHit);
  466.                 }
  467.                 if (!EmptyRgn(((WindowPeek)theDialog)->updateRgn)) {
  468.                     BeginUpdate(theDialog);
  469.                     DrawDialog(theDialog);
  470.                     EndUpdate(theDialog);
  471.                 }            
  472.             }
  473.             ClipRect(&theDialog->portRect);
  474.             
  475.             if (locals->isBWPort) {
  476.                 SetPort(locals->window);
  477.  
  478.                 CopyRgn(theDialog->visRgn, locals->window->visRgn);
  479.             //    SetPort((GrafPtr)&locals->colorPort);
  480.             //    BlockMove(theDialog, &locals->bwPort, sizeof(GrafPort)); /* Blast back */
  481.             //    BlockMove(&locals->colorPort, theDialog, sizeof(GrafPort)); /* Blast in a color port */
  482.             }
  483.             
  484.             PlotIconSuite(&iconBox, atNone, ttNone, globals->iconSuites[locals->stage]);
  485.             
  486.             if (locals->isBWPort) {
  487.                 SetEmptyRgn(locals->window->visRgn);
  488.             //    BlockMove(&locals->bwPort, theDialog, sizeof(GrafPort)); /* Blast back */
  489.             }
  490.  
  491.             DisposeRgn(firstMask);
  492.             DisposeRgn(secondMask);
  493.             SetPort(currentPort);
  494.             ++locals->stage;
  495.         }
  496.     }
  497.     
  498.     if (locals->filterProc) {
  499.         return locals->filterProc(theDialog, theEvent, itemHit);
  500.     } else return false;
  501. }
  502.  
  503.  
  504.